package com.agger.harmonyosthemeseditor.intelligent;

import ohos.agp.colors.RgbColor;
import ohos.media.image.PixelMap;
import ohos.media.image.common.ImageInfo;
import ohos.media.image.common.Position;

import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.util.zip.Adler32;
import java.util.zip.CRC32;

public class ImageCodec
{
    //PNG_signature=0x89,0x50,0x4E,0X47,0X0D,0X0A,0X1A,0X0A
    public static final byte[] PNG_signature = new byte[]{-119,80,78,71,13,10,26,10};
    //块长度4字节，IHDR标记4字节，像素宽4字节，像素高4字节，图像位深1字节，颜色类型1字节（其中带透明通道的真彩图为6），压缩方法1字节（一般是0，即deflate、inflate），滤波器方法1字节（一般是0，即自适应），隔行扫描方法1字节（0表示非隔行扫描，1为Adam7），CRC码4字节
    //由于图标文件都是192*192，而且其它参数也是一致的，因此CRC码也是固定的，这里直接作为一个整体byte数组
    public static final byte[] PNG_IHDR_Icon = new byte[]{0,0,0,13,73,72,68,82,0,0,0,-64,0,0,0,-64,8,6,0,0,0,82,-36,108,7};
    //IDAT块标记，共4字节
    public static final byte[] PNG_IDAT_TYPE = new byte[]{73,68,65,84};
    //IDAT块数据内部头，共7字节，第1个字节表示压缩方法和压缩信息，第2个字节表示标志信息，第3个字节的第一位是最后一个块标记、第二位和第三位是编码方法，第4个和第5个字节表示块中数据字节的长度，第6个和第7个字节是第4个和第5个字节的补码
    //由于图标文件都是192*192，并且这里一律采用非压缩方法，因此这个头是固定，这里直接作为一个整体byte数组，方便快速调用
    public static final byte[] PNG_IDAT_BasicInfo_Icon = new byte[]{120,1,0,-1,-1,0,0};
    //块长度4字节,IEND标记4字节,CRC码4字节,该byte数组也是固定的
    public static final byte[] PNG_IEND = new byte[]{0,0,0,0,73,69,78,68,-82,66,96,-126};

    public static byte[] getValueByte(int val)
    {
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.putInt(0, val);
        return buffer.array();
    }

    public static byte[] getAdler32(byte[] bytes)
    {
        Adler32 adler32= new Adler32();
        adler32.update(bytes);
        return getValueByte((int)adler32.getValue());
    }

    public static byte[] getCRC32(byte[] bytes)
    {
        CRC32 crc32 = new CRC32();
        crc32.update(bytes);
        return getValueByte((int)crc32.getValue());
    }

    public static byte[] getPixelMapData(PixelMap mPixelMap)
    {
        try
        {
            System.gc();
            ImageInfo mImageInfo = mPixelMap.getImageInfo();
            int mWidth = mImageInfo.size.width;
            int mHeight = mImageInfo.size.height;
            byte[] returnValue = new byte[(mWidth*4+1)*mHeight];
            for (int h = 0; h < mHeight; h++)
            {
                returnValue[h+h*mWidth] = 0;
                for (int w = 0; w < mWidth; w++)
                {
                    RgbColor c = RgbColor.fromArgbInt(mPixelMap.readPixel(new Position(w, h)));
                    returnValue[h+h*mWidth*4+w*4+1] = (byte)c.getRed();
                    returnValue[h+h*mWidth*4+w*4+2] = (byte)c.getGreen();
                    returnValue[h+h*mWidth*4+w*4+3] = (byte)c.getBlue();
                    returnValue[h+h*mWidth*4+w*4+4] = (byte)c.getAlpha();
                }
            }
            return returnValue;
        }catch (Exception e) { return null;}
    }

    public static byte[] mergeBytes(byte[] data1, byte[] data2)
    {
        byte[] data3 = new byte[data1.length + data2.length];
        System.arraycopy(data1, 0, data3, 0, data1.length);
        System.arraycopy(data2, 0, data3, data1.length, data2.length);
        return data3;
    }

    public static byte[] getAllIdatBytes(byte[] header,byte[] pxm_data,byte[] adler32_data)
    {
        return mergeBytes(mergeBytes(mergeBytes(PNG_IDAT_TYPE,header),pxm_data),adler32_data);
    }

    public static boolean PixelMaptoFile_Icon(PixelMap mPixelMap,String fileName)
    {
        try
        {
            byte[] pixelMapData = getPixelMapData(mPixelMap);
            byte[] pixelMapData_Adler32 = getAdler32(pixelMapData);
            byte[] fullIdatData = getAllIdatBytes(PNG_IDAT_BasicInfo_Icon,pixelMapData,pixelMapData_Adler32);
            File outputImg = new File(fileName);
            FileOutputStream out = new FileOutputStream(outputImg);
            if(outputImg.createNewFile())
            {
                out.write(PNG_signature);
                out.write(PNG_IHDR_Icon);
                out.write(getValueByte(147659));
                out.write(PNG_IDAT_TYPE);
                out.write(PNG_IDAT_BasicInfo_Icon);
                out.write(pixelMapData);
                out.write(pixelMapData_Adler32);
                out.write(getCRC32(fullIdatData));
                out.write(PNG_IEND);
                System.gc();
                out.flush();
                out.close();
                return true;
            }else return false;
        }catch (Exception e){e.printStackTrace();return false;}
    }
}
